package com.simple.crawler.connect.http;

import com.simple.crawler.connect.Connection;
import com.simple.crawler.connect.http.request.HttpRequest;
import com.simple.crawler.connect.http.response.HttpResponse;
import com.simple.crawler.constant.ExceptionCode;
import com.simple.crawler.constant.HttpMethod;
import com.simple.crawler.exception.CrawlerRuntimeException;
import com.simple.crawler.utils.CrawlerLogger;
import com.simple.crawler.utils.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.HttpClientBuilder;

import java.io.ByteArrayInputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName HttpConnection
 * @Author Administrator
 * @Desc TODO
 * @CreateTime 2019/8/3 22:23
 */
public class HttpConnection extends Connection<HttpRequest, HttpResponse> {

    private static CrawlerLogger logger = CrawlerLogger.getLogger(HttpConnection.class);

    private String charSet;

    private HttpRequest request;

    private HttpResponse response;

    private HttpClient httpClient = HttpClientBuilder.create().build();

    public HttpConnection() {
    }

    public HttpConnection(String charSet) {
        this.charSet = charSet;
    }

    @Override
    public HttpConnection validate(HttpRequest request) throws Exception {
        if (request == null || StringUtils.isBlank(request.getUrl())) {
            throw new CrawlerRuntimeException(ExceptionCode.REQUEST_ERROR);
        }
        this.request = request;
        return this;
    }

    @Override
    public HttpResponse accept() throws Exception {
        if (this.request == null) {
            throw new CrawlerRuntimeException(ExceptionCode.REQUEST_ERROR);
        }
        HttpRequestBase httpReq = HttpMethod.createRequest(this.request.getMethod(), this.request.getUrl());
        //设置请求头
        if (!this.request.getHeader().isEmpty()) {
            this.request.getHeader().forEach((k, v) -> httpReq.setHeader(k, v));
        }
        RequestConfig.Builder configBuilder = RequestConfig.custom();
        //设置代理
        if (this.request.getProxy() != null) {
            configBuilder.setProxy(new HttpHost(request.getProxy().getHost(), request.getProxy().getPort()));
        }
        httpReq.setConfig(configBuilder.build());
        //设置请求体
        if (httpReq instanceof HttpEntityEnclosingRequestBase && this.request.getBody() != null) {
            ((HttpEntityEnclosingRequestBase) httpReq).setEntity(new InputStreamEntity(new ByteArrayInputStream(this.request.getBody())));
        }
        CloseableHttpResponse httpResp = (CloseableHttpResponse) httpClient.execute(httpReq);
        this.response = new HttpResponse();
        this.response.setResponseCode(httpResp.getStatusLine().getStatusCode());
        Map<String, String> headerMap = new HashMap<>();
        for (Header header: httpResp.getAllHeaders()) {
            headerMap.put(header.getName(), header.getValue());
        }
        if (StringUtils.isNotBlank(this.charSet)) {
            this.response.setCharSet(this.charSet);
        }
        this.response.setHeader(headerMap);
        this.response.setContent(httpResp.getEntity().getContent());
        return this.response;
    }


}
